#include "c3dwidget.h"

using namespace std;

bool little3d_than(const RelatWellData& s1, RelatWellData& s2)
{
    return (s1.eDepth <= s2.eDepth);
}


c3DWidget::c3DWidget(QWidget *parent) : QWidget(parent)
{
    //设置整体布局
    QHBoxLayout *layoutall = new QHBoxLayout(this);
    //新建使用的控件
    scatter = new Q3DScatter();
    camera = new Q3DCamera(scatter);
    container = QWidget::createWindowContainer(scatter);
    container->setMinimumSize(QSize(800, 800));
    container->setWindowTitle("3D Smooth Curve Example");


//    // 定义一些关键点（折线的顶点）
//    keyPoints = {
//        {0.0f, 0.0f, 706.0f},
//        {0.0f, 0.0f, 706.0f},
////        {0.0f, 0.0f, 757.0f},
////        {0.0f, 0.0f, 800.0f},
////        {0.0f, 0.0f, 850.0f},
//        {0.0f, 0.0f, 960.0f},
//        {0.0f, 0.0f, 960.0f},
//    };

//    // 通过 Catmull-Rom 插值生成平滑曲线数据
//    smoothCurvePoints = interpolateCatmullRom(keyPoints, 5000);

    // 创建曲线系列，并填充平滑曲线数据
    series = new QScatter3DSeries();
    series->setItemSize(0.05);  // 调整点大小
    series->setBaseColor(Qt::cyan);  // 设置颜色
//    series->dataProxy()->resetArray(generateSmoothCurveData(smoothCurvePoints));

    //创建原始井与新井曲线
    originseries = new QScatter3DSeries();
    newseries = new QScatter3DSeries();

    // 将系列添加到 Q3DScatter 中
    scatter->addSeries(series);
    scatter->addSeries(originseries);
    scatter->addSeries(newseries);

    scatter->axisX()->setRange(-50,50);
    scatter->axisY()->setRange(-50,50);
    scatter->axisZ()->setRange(707,960);

    // 配置图表样式
    scatter->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow);
    scatter->activeTheme()->setLabelBackgroundEnabled(false);



    layoutall->addWidget(container);
}

c3DWidget::~c3DWidget(void)
{

}

/* Catmull-Rom 样条插值：计算平滑曲线上的点 */
QVector<QVector3D> c3DWidget::interpolateCatmullRom(const QVector<QVector3D>& points, int numInterpolatedPoints)
{
    QVector<QVector3D> result;
    if (points.size() < 4) return points;  // 至少需要4个点

    for (int i = 1; i < points.size() - 2; ++i) {
        for (int j = 0; j <= numInterpolatedPoints; ++j) {
            float t = j / float(numInterpolatedPoints);  // 插值参数

            // Catmull-Rom 样条公式
            float t2 = t * t;
            float t3 = t2 * t;

            QVector3D p0 = points[i - 1];
            QVector3D p1 = points[i];
            QVector3D p2 = points[i + 1];
            QVector3D p3 = points[i + 2];

            QVector3D point = 0.5f * (
                        (2.0f * p1) +
                        (-p0 + p2) * t +
                        (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 +
                        (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3
                        );

            result.append(point);
        }
    }
    return result;
}

/* 工具函数：将 QVector<QVector3D> 转为 QScatterDataArray */
QScatterDataArray* c3DWidget::generateSmoothCurveData(const QVector<QVector3D>& points)
{
    QScatterDataArray* dataArray = new QScatterDataArray;
    dataArray->resize(points.size());
    for (int i = 0; i < points.size(); ++i) {
        (*dataArray)[i].setPosition(points[i]);
    }
    return dataArray;
}

/* 根据角度和距离计算新点的位置 (输入中心点并且输入角度和相对距离 确定相对点坐标) */
QVector3D c3DWidget::calculateNewPoint(const QVector3D &center, double angle, double distance)
{
    // 将角度转换为弧度
    double radian = qDegreesToRadians(angle);

    // 三角函数计算新点的 x 和 y 坐标
    double newX = center.x() + distance * qCos(radian);
    double newY = center.y() + distance * qSin(radian);
    double newZ = center.z();

    return QVector3D(newX, newY, newZ);
}



/* 绘制原井轨迹 */
void c3DWidget::vDrawOriginWell(QList<RelatWellData> pdata)
{
    //数据个数
    quint32 count = pdata.size();

    // 定义一些关键点（折线的顶点）
    QVector<QVector3D> originPoints;
    QVector3D oPoints;

    std::sort(pdata.begin(), pdata.end(),little3d_than);
    scatter->axisZ()->setRange(pdata[0].eDepth,pdata[count-1].eDepth);

    //逐个数据进行
    for (int i = 0; i < count; ++i)
    {
        oPoints = {0,0,pdata[i].eDepth};
        originPoints.append(oPoints);
    }

    // 通过 Catmull-Rom 插值生成平滑曲线数据
    originCurvePoints = interpolateCatmullRom(originPoints, 1000);
    originseries->setItemSize(0.03);  // 调整点大小
    originseries->setBaseColor(Qt::cyan);  // 设置颜色
    originseries->dataProxy()->resetArray(generateSmoothCurveData(originCurvePoints));

}

/* 绘制新井轨迹 */
void c3DWidget::vDrawNewWell(QList<RelatWellData> pdata)
{
    //数据个数
    quint32 count = pdata.size();

    // 定义一些关键点（折线的顶点）
    QVector<QVector3D> newPoints;
    QVector3D oPoints;
    QVector3D nPoints;

    //先绘制原始井轨迹
    vDrawOriginWell(pdata);

    std::sort(pdata.begin(), pdata.end(),little3d_than);
    //逐个数据进行
    for (int i = 0; i < count; ++i)
    {
        oPoints = {0,0,pdata[i].eDepth};
        nPoints = calculateNewPoint(oPoints,pdata[i].eAzimuth,pdata[i].eDistan);
        newPoints.append(nPoints);
    }

    // 通过 Catmull-Rom 插值生成平滑曲线数据
    newCurvePoints = interpolateCatmullRom(newPoints, 1000);
    newseries->setItemSize(0.03);  // 调整点大小
    newseries->setBaseColor(Qt::blue);  // 设置颜色
    newseries->dataProxy()->resetArray(generateSmoothCurveData(newCurvePoints));
}






